package com.ouyunc.file.plugins.cos;

import com.ouyunc.common.constant.enums.FilePluginEnum;
import com.ouyunc.common.context.SpringContextHolder;
import com.ouyunc.common.utils.SnowflakeUtil;
import com.ouyunc.file.plugins.AbstractUploaderDownloader;
import com.ouyunc.file.plugins.base.DownloadConfig;
import com.ouyunc.file.plugins.base.FileReturn;
import com.ouyunc.file.plugins.base.UploadConfig;
import com.ouyunc.file.plugins.minio.MinIoFilePlugin;
import com.ouyunc.file.plugins.properties.FileProperties;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.TransferManagerConfiguration;
import com.qcloud.cos.transfer.Upload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 腾讯云 cos 对象存储插件
 */
public class CosFilePlugin extends AbstractUploaderDownloader {
    private static final Logger log = LoggerFactory.getLogger(MinIoFilePlugin.class);
    private static final FileProperties fileProperties;

    private static TransferManager manager;

    private static COSClient cosClient;


    static {
        // 读取配置文件中的数据
        fileProperties = SpringContextHolder.getBean(FileProperties.class);
        // 进行初始化并配置cosClient
        // 设置用户身份信息。
        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
        //用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
        //用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
        COSCredentials cred = new BasicCOSCredentials(fileProperties.getCos().getSecretId(), fileProperties.getCos().getSecretKey());

        // ClientConfig 中包含了后续请求 COS 的客户端设置：
        ClientConfig clientConfig = new ClientConfig();

        // 设置 bucket 的地域
        // COS_REGION 请参见 https://cloud.tencent.com/document/product/436/6224
        clientConfig.setRegion(new Region(fileProperties.getCos().getRegion()));

        // 设置请求协议, http 或者 https
        // 5.6.53 及更低的版本，建议设置使用 https 协议
        // 5.6.54 及更高版本，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);

        // 以下的设置，是可选的：

        // 设置 socket 读取超时，默认 30s
        clientConfig.setSocketTimeout(30*1000);
        // 设置建立连接超时，默认 30s
        clientConfig.setConnectionTimeout(30*1000);

        // 如果需要的话，设置 http 代理，ip 以及 port
//        clientConfig.setHttpProxyIp("httpProxyIp");
//        clientConfig.setHttpProxyPort(80);

        // 生成 cos 客户端。
        cosClient =  new COSClient(cred, clientConfig);

        // 创建一个 COSClient 实例，这是访问 COS 服务的基础实例。
        // 详细代码参见本页: 简单操作 -> 创建 COSClient
        //COSClient cosClient = createCOSClient();
        // 自定义线程池大小，建议在客户端与 COS 网络充足（例如使用腾讯云的 CVM，同地域上传 COS）的情况下，设置成16或32即可，可较充分的利用网络资源
        // 对于使用公网传输且网络带宽质量不高的情况，建议减小该值，避免因网速过慢，造成请求超时。
        ExecutorService threadPool = Executors.newFixedThreadPool(16);
        // 传入一个 threadpool, 若不传入线程池，默认 TransferManager 中会生成一个单线程的线程池。
        TransferManager transferManager = new TransferManager(cosClient, threadPool);
        // 设置高级接口的配置项
        // 分块上传阈值和分块大小分别为 5MB 和 1MB
        TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
        transferManagerConfiguration.setMultipartUploadThreshold(5*1024*1024);
        transferManagerConfiguration.setMinimumUploadPartSize(1*1024*1024);
        transferManager.setConfiguration(transferManagerConfiguration);
        manager = transferManager;
    }

    @Override
    public FilePluginEnum pluginEnum() {
        return FilePluginEnum.COS;
    }





    @Override
    public void download(String fileUri, String fileName, DownloadConfig config) {

    }

    @Override
    public void download(byte[] bytes, String fileName, DownloadConfig config) {

    }

    /**
     * cos 上传接口
     * @param file
     * @param fileItem 配置项
     * @return
     */
    @Override
    public FileReturn upload(MultipartFile file, UploadConfig fileItem) {
        log.error("minio 开始上传文件...");
        long fileSize = file.getSize();
        String originalFilename = file.getOriginalFilename();
        String[] fileRegex = originalFilename.split("\\.", -1);
        String fileSuffix = "." + fileRegex[fileRegex.length - 1];
        String newFileName = SnowflakeUtil.nextId() + "_" + originalFilename;
        try (InputStream inputStream = file.getInputStream()) {
            // 高级接口会返回一个异步结果Upload
            // 可同步地调用 waitForUploadResult 方法等待上传完成，成功返回 UploadResult, 失败抛出异常
            Upload upload = manager.upload(fileItem.getBucketName(), newFileName, inputStream, new ObjectMetadata());
            UploadResult uploadResult = upload.waitForUploadResult();
            return new FileReturn(originalFilename, newFileName, fileSuffix, fileProperties.getCos().getEndpoint() + uploadResult.getKey(), fileSize);
        } catch (CosClientException | InterruptedException | IOException e) {
            log.error("腾讯云cos对象存储上传失败！原因：{}",e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("腾讯云cos对象存储上传失败！");
        }
    }

    @Override
    public FileReturn copy(String srcFilePath, UploadConfig fileItem) {
        return null;
    }


}
